<template>
	<div>
		<div style="position: relative;">
			<Toolbar v-if="toolbarVisible"></Toolbar>
			<div style="display: flex;">
				<palette @addComponent="addComponentHandler"></palette>
				<div style="width:2000px;height:1000px;background-color: white;flex-grow: 1;position:relative;"
					id="efContainer" ref="efContainer" class="container">
					<i class="el-icon-share"
						style="position: absolute;left:0;top: 0;border: 1px solid lightgray;padding:5px;"
						@click="onWorkflowClickHandler"></i>
					<template v-for="(item) in nodeList">
						<StartNode :nodeModel="item" v-if="item.type=='start'" :id="item.id" :key="item.id"
							@click="onNodeClickHandler(item)">
						</StartNode>
						<TaskNode :nodeModel="item" v-if="item.type=='task'" :id="item.id" :key="item.id"
							@click="onNodeClickHandler(item)">
						</TaskNode>
						<EndNode :nodeModel="item" v-if="item.type=='end'" :id="item.id" :key="item.id"
							@click="onNodeClickHandler(item)">
						</EndNode>
						<ServiceNode :nodeModel="item" v-if="item.type=='service'" :id="item.id" :key="item.id"
							@click="onNodeClickHandler(item)">
						</ServiceNode>
						<DecisionNode :nodeModel="item" v-if="item.type=='decision'" :id="item.id" :key="item.id"
							@click="onNodeClickHandler(item)">
						</DecisionNode>
						<ForkNode :nodeModel="item" v-if="item.type=='fork'" :id="item.id" :key="item.id"
							@click="onNodeClickHandler(item)">
						</ForkNode>
						<JoinNode :nodeModel="item" v-if="item.type=='join'" :id="item.id" :key="item.id"
							@click="onNodeClickHandler(item)">
						</JoinNode>
					</template>
				</div>
			</div>
		</div>
		<el-drawer title="" v-model="drawerVisible" :append-to-body="true">
			<el-form ref="form" label-width="100px">
				<el-form-item label="名称">
					<el-input v-model="currentLineModel.name" size="small"></el-input>
				</el-form-item>
				<el-form-item label="显示">
					<el-input v-model="currentLineModel.label" size="small" @change="onLineLabelChangeHandler">
					</el-input>
				</el-form-item>
				<el-form-item label="条件">
					<el-input v-model="currentLineModel.condition" size="small" type="textarea"></el-input>
				</el-form-item>
				<el-divider content-position="left">事件</el-divider>
				<el-form-item label="take事件">
					<el-input v-model="currentLineModel.takeEventExpression" size="small" type="textarea"></el-input>
				</el-form-item>
			</el-form>
		</el-drawer>
		<el-drawer title="" v-model="workflowDrawerVisible" :append-to-body="true">
			<el-form ref="form" label-width="100px">
				<el-form-item label="编码">
					<el-input v-model="currentWorkflow.code" size="small" :readonly="true"></el-input>
				</el-form-item>
				<el-form-item label="名称">
					<el-input v-model="currentWorkflow.name" size="small"></el-input>
				</el-form-item>
				<el-form-item label="关联表">
					<el-select size="mini" v-model="currentWorkflow.irModelId" placeholder="请选择" clearable filterable
						@change="onTableSelectChangeHandler">
						<el-option v-for="item in tableList" :key="item.value" :label="item.name" :value="item.value">
						</el-option>
					</el-select>
				</el-form-item>
				<el-form-item label="关联字段">
					<el-select size="mini" v-model="displayColumnList" placeholder="请选择" clearable filterable multiple>
						<el-option v-for="item in columnList" :key="item.value" :label="item.name" :value="item.value">
						</el-option>
					</el-select>
				</el-form-item>
				<el-form-item label="关联表单">
					<el-input v-model="currentWorkflow.formCode" size="small"></el-input>
				</el-form-item>
				<el-form-item label="关联移动端表单">
					<el-input v-model="currentWorkflow.mobileFormCode" size="small"></el-input>
				</el-form-item>
				<el-divider content-position="left">流程事件</el-divider>
				<el-form-item label="start事件">
					<el-input v-model="currentWorkflow.startEventExpression" size="small" type="textarea"></el-input>
				</el-form-item>
				<el-form-item label="end事件">
					<el-input v-model="currentWorkflow.endEventExpression" size="small" type="textarea"></el-input>
				</el-form-item>
			</el-form>
		</el-drawer>
	</div>
</template>

<script>
	import Toolbar from './Toolbar.vue';
	import StartNode from './StartNode.vue';
	import TaskNode from './TaskNode.vue';
	import EndNode from './EndNode.vue';
	import ServiceNode from './ServiceNode.vue';
	import modelFactory from './ModelFactory.js';
	import Palette from './Palette.vue';
	import DecisionNode from './DecisionNode.vue';
	import ForkNode from './ForkNode.vue';
	import JoinNode from './JoinNode.vue';
	import {
		jsPlumb
	} from 'jsplumb'
	import {
		easyFlowMixin
	} from './mixins';
	import restUtil from '@/utils/restUtil.js';
	export default {
		name: 'WorkflowDesiger',
		components: {
			Toolbar,
			StartNode,
			TaskNode,
			EndNode,
			ServiceNode,
			Palette,
			DecisionNode,
			ForkNode,
			JoinNode
		}, // 一些基础配置移动该文件中
		mixins: [easyFlowMixin],
		beforeMount() {
			this.$store.state.workflowDesigner = this;
			//this.startNodeModel = modelFactory.createModel(this.createContext, "start");
			//this.nodeList.push(this.startNodeModel);
		},
		mounted() {
			this.jsPlumb = jsPlumb.getInstance();
			this.jsPlumbInit();
			this.init();
		},
		props: ["paraMap"],
		data() {
			return {
				startNodeModel: {},
				nodeList: [],
				lineList: [],
				currentElementId: 0,
				createContext: {},
				selectedComponent: null,
				// jsPlumb 实例
				jsPlumb: null,
				activeElement: {
					// 可选值 node 、line
					type: undefined,
					// 节点ID
					nodeId: undefined,
					// 连线ID
					sourceId: undefined,
					targetId: undefined
				},
				drawerVisible: false,
				currentLineModel: {},
				workflowDrawerVisible: false,
				currentWorkflow: {
					"code": "",
					"name": "",
					"formCode": "",
					"mobileFormCode": "",
					"documentExpression": "",
					"startEventExpression": "",
					"endEventExpression": ""
				},

				toolbarVisible: true,
				tableList:[],
				displayColumnList:[],
				columnList: [],
			}
		},
		methods: {
			addComponentHandler(type) {
				var nodeModel = this.createNodeModel(type);
				nodeModel["top"] = "0px";
				nodeModel["left"] = "0px";
				this.nodeList.push(nodeModel);

				this.$nextTick(function() {
					this.jsPlumb.makeSource(nodeModel.id, this.jsplumbSourceOptions)
					this.jsPlumb.makeTarget(nodeModel.id, this.jsplumbTargetOptions)
					this.jsPlumb.draggable(nodeModel.id, {
						containment: 'parent',
						stop: function(el) {
							// 拖拽节点结束后的对调
							console.log('拖拽结束: ', el)
						}
					})
				})
			},
			createNodeModel(type) {
				this.currentElementId++;
				this.createContext.currentElementId = this.currentElementId;
				var model = modelFactory.createModel(this.createContext, type);
				return model;
			},
			init() {
				var that = this;
				if (this.paraMap == undefined) {
					return;
				}
				var code = this.paraMap["code"];
				if (code == undefined) {
					return;
				}
				var view=this.paraMap["view"];
				if(view!=undefined){
					this.toolbarVisible=false;
				}
				restUtil.getAction(this,"devworkflowdesigner/init?code=" + code).then(
					function(response) {
						if (response.data.code == 1) {
							that.createContext.code = response.data.workflowCode;
							that.currentWorkflow.code = response.data.workflowCode;
							that.currentWorkflow.name = response.data.name;
							that.currentWorkflow.formCode = response.data.formCode;
							that.currentWorkflow.mobileFormCode = response.data.mobileFormCode;
							if (response.data.workflowJson != null) {
								var workflowJson = JSON.parse(response.data.workflowJson);
								that.nodeList = workflowJson.nodeList;
								that.lineList = workflowJson.lineList;
								that.currentWorkflow.startEventExpression = workflowJson.startEventExpression;
								that.currentWorkflow.endEventExpression = workflowJson.endEventExpression;
								that.currentWorkflow.documentExpression = workflowJson.documentExpression;
								that.dataReload();
							}
							if (response.data.currentElementId != null) {
								that.currentElementId = response.data.currentElementId;
								that.createContext.currentElementId = response.data.currentElementId;
							}
							that.tableList=response.data.tableList;
							that.columnList=response.data.columnList;
							
                            that.currentWorkflow.irModelId=response.data.irModelId;
							var displayColumnList=response.data.displayColumnList;
							if(displayColumnList==null ||displayColumnList==""){
								that.displayColumnList=[];
							}else{
								that.displayColumnList=displayColumnList.split(",");
							}
                           
						} else {
							that.$alert(response.data.message, '提示')
						}
					});
			},
			getNodeModelById(id) {
				for (var i = 0; i < this.nodeList.length; i++) {
					if (this.nodeList[i].id == id) {
						return this.nodeList[i];
					}
				}
			},
			setSelectedComponent(selectedComponent) {
				this.selectedComponent = selectedComponent;
			},
			getSelectedComponent() {
				return this.selectedComponent;
			},
			jsPlumbInit() {
				this.jsPlumb.ready(() => {
					// 导入默认配置
					this.jsPlumb.importDefaults(this.jsplumbSetting)
					// 会使整个jsPlumb立即重绘。
					this.jsPlumb.setSuspendDrawing(false, true);
					// 初始化节点
					this.loadEasyFlow()
					// 单点击了连接线, https://www.cnblogs.com/ysx215/p/7615677.html
					this.jsPlumb.bind('click', (conn) => {
						this.activeElement.type = 'line'
						this.activeElement.sourceId = conn.sourceId
						this.activeElement.targetId = conn.targetId
						for (var i = 0; i < this.lineList.length; i++) {
							if (this.lineList[i].from == conn.sourceId && this.lineList[i].to == conn
								.targetId) {
								this.currentLineModel = this.lineList[i];
							}
						}
						this.drawerVisible = true;
					})
					// 连线
					this.jsPlumb.bind("connection", (evt) => {
						this.currentElementId++;
						let from = evt.source.id
						let to = evt.target.id
						this.lineList.push({
							from: from,
							to: to,
							name: "line" + this.currentElementId
						})
					})

					// 删除连线回调
					this.jsPlumb.bind("connectionDetached", (evt) => {
						this.deleteLine(evt.sourceId, evt.targetId)
					})

					// 改变线的连接节点
					this.jsPlumb.bind("connectionMoved", (evt) => {
						this.changeLine(evt.originalSourceId, evt.originalTargetId)
					})

					// 连线右击
					this.jsPlumb.bind("contextmenu", (evt) => {
						console.log('contextmenu', evt)
					})

					// 连线
					this.jsPlumb.bind("beforeDrop", (evt) => {
						let from = evt.sourceId
						let to = evt.targetId
						if (from === to) {
							this.$message.error('节点不支持连接自己')
							return false
						}
						if (this.hasLine(from, to)) {
							this.$message.error('该关系已存在,不允许重复创建')
							return false
						}
						if (this.hashOppositeLine(from, to)) {
							this.$message.error('不支持两个节点之间连线回环');
							return false
						}
						this.$message.success('连接成功')
						return true;
					})

					// beforeDetach
					this.jsPlumb.bind("beforeDetach", (evt) => {
						console.log('beforeDetach', evt)
					})
					this.jsPlumb.setContainer(this.$refs.efContainer)
				})
			},
			hasLine(from, to) {
				for (var i = 0; i < this.lineList.length; i++) {
					var line = this.lineList[i]
					if (line.from === from && line.to === to) {
						return true
					}
				}
				return false
			},
			// 是否含有相反的线
			hashOppositeLine(from, to) {
				return this.hasLine(to, from)
			}, // 删除线
			deleteLine(from, to) {
				this.lineList = this.lineList.filter(function(line) {
					if (line.from == from && line.to == to) {
						return false
					}
					return true
				})
			},
			dataReload() {
				this.jsPlumb = jsPlumb.getInstance()
				this.$nextTick(() => {
					this.jsPlumbInit()
				});
			}, // 加载流程图
			loadEasyFlow() {
				// 初始化节点
				for (var i = 0; i < this.nodeList.length; i++) {
					let node = this.nodeList[i]
					// 设置源点，可以拖出线连接其他节点
					this.jsPlumb.makeSource(node.id, this.jsplumbSourceOptions)
					// // 设置目标点，其他源点拖出的线可以连接该节点
					this.jsPlumb.makeTarget(node.id, this.jsplumbTargetOptions)
					this.jsPlumb.draggable(node.id, {
						containment: 'parent',
						stop: function(el) {
							// 拖拽节点结束后的对调
							console.log('拖拽结束: ', el)
						}
					})
				}
				// 初始化连线
				for (i = 0; i < this.lineList.length; i++) {
					let line = this.lineList[i]
					var connParam = {
						source: line.from,
						target: line.to,
						label: line.label ? line.label : '',
						connector: line.connector ? line.connector : '',
						anchors: line.anchors ? line.anchors : undefined,
						paintStyle: line.paintStyle ? line.paintStyle : undefined,
					}
					this.jsPlumb.connect(connParam, this.jsplumbConnectOptions)
				}
			}, // 删除激活的元素
			deleteElement() {
				if (this.activeElement.type === 'node') {
					this.deleteNode(this.activeElement.nodeId)
				} else if (this.activeElement.type === 'line') {
					this.$confirm('确定删除所点击的线吗?', '提示', {
						confirmButtonText: '确定',
						cancelButtonText: '取消',
						type: 'warning'
					}).then(() => {
						var conn = this.jsPlumb.getConnections({
							source: this.activeElement.sourceId,
							target: this.activeElement.targetId
						})[0]
						this.jsPlumb.deleteConnection(conn)
					}).catch(() => {})
				}
			},
			deleteNode(nodeId) {
				this.$confirm('确定要删除节点' + nodeId + '?', '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning',
					closeOnClickModal: false
				}).then(() => {
					/**
					 * 这里需要进行业务判断，是否可以删除
					 */
					this.nodeList = this.nodeList.filter(function(node) {
						if (node.id === nodeId) {
							// 伪删除，将节点隐藏，否则会导致位置错位
							// node.show = false
							return false
						}
						return true
					})
					this.$nextTick(function() {
						this.jsPlumb.removeAllEndpoints(nodeId);
					})
				}).catch(() => {})
				return true
			}, // 设置连线条件
			setLineLabel(from, to, label) {
				var conn = this.jsPlumb.getConnections({
					source: from,
					target: to
				})[0]
				conn.setLabel({
					label: label,
				})
				this.lineList.forEach(function(line) {
					if (line.from == from && line.to == to) {
						//line.label = label
					}
				})
			},
			onLineLabelChangeHandler() {
				this.setLineLabel(this.currentLineModel.from, this.currentLineModel.to, this.currentLineModel.label)
			},
			onNodeClickHandler(item) {
				this.activeElement.type = "node";
				this.activeElement.nodeId = item.id;
			},
			onWorkflowClickHandler() {
				this.workflowDrawerVisible = true;
			},onTableSelectChangeHandler(){
				var that=this;
				restUtil.getAction(this,"devworkflowdesigner/onTableSelectChangeHandler?irModelId="+this.currentWorkflow.irModelId).then(
					function(response) {
						if (response.data.code == 1) {
							that.columnList=response.data.columnList;
							that.displayColumnList=[];
					}
				});
			}
		},
	}
</script>

<style>
	
</style>
